package cn.wx.common.utils;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.format.annotation.DateTimeFormat;

import java.lang.reflect.Field;
/**
 *   @description : 对象转化类
 *   ---------------------------------
 *   @author zj
 *   @since 2017-10-27
 */
@SuppressWarnings({"rawtypes","unchecked"})
public class ObjectTranslator {

	public static List<Field> getBeanFields(Class cls){
		
		List<Field> fieldsAll = new ArrayList<>();
		Field[] fields = cls.getDeclaredFields();
		fieldsAll.addAll(Arrays.asList(fields));
		
		while (cls.getSuperclass() != null) {
			Field[] fields_ = cls.getSuperclass().getDeclaredFields();
			fieldsAll.addAll(Arrays.asList(fields_));
			cls = cls.getSuperclass();
		}
		return fieldsAll;
    }
	
	public static Map objectToMap(Object myObj)  {
		/*try {*/
			Class type = myObj.getClass();
			List<Field> fields = getBeanFields(type);
			
			if(fields == null){
				return null;
			}
			
			Map<String,Object> returnMap = new HashMap<>();
			try {
				for(Field field : fields){
					 field.setAccessible(true); 
					 Object fieldValue_ = field.get(myObj);
					 String fieldName = field.getName();
					 boolean fieldHasAnno = field.isAnnotationPresent(DateTimeFormat.class);
					 if(fieldHasAnno){
						 DateTimeFormat fieldAnno = field.getAnnotation(DateTimeFormat.class);
						 SimpleDateFormat format = new SimpleDateFormat(fieldAnno.pattern());
						 fieldValue_ = format.format(fieldValue_);
					 }
					 returnMap.put(fieldName, fieldValue_);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			return returnMap;
	}

	private static Map<Object, Object> mapToMap(Map<Object, Object> orignMap) {
		Map<Object, Object> resultMap = new HashMap<Object, Object>();
		for (Entry<Object, Object> entry : orignMap.entrySet()) {
			Object key = entry.getKey();
			Object resultKey = null;
			if (key instanceof Collection) {
				resultKey = arrayToMap((Collection) key);
			} else if (key instanceof Map) {
				resultKey = mapToMap((Map) key);
			} else {
				if (key instanceof String || key instanceof Boolean || key instanceof Byte || key instanceof Short
						|| key instanceof Integer || key instanceof Long || key instanceof Float
						|| key instanceof Double || key instanceof Enum) {
					if (key != null) {
						resultKey = key;
					}
				} else {
					resultKey = objectToMap(key);
				}
			}

			Object value = entry.getValue();
			Object resultValue = null;
			if (value instanceof Collection) {
				resultValue = arrayToMap((Collection) value);
			} else if (value instanceof Map) {
				resultValue = mapToMap((Map) value);
			} else {
				if (value instanceof String || value instanceof Boolean || value instanceof Byte
						|| value instanceof Short || value instanceof Integer || value instanceof Long
						|| value instanceof Float || value instanceof Double || value instanceof Enum) {
					if (value != null) {
						resultValue = value;
					}
				} else {
					resultValue = objectToMap(value);
				}
			}

			resultMap.put(resultKey, resultValue);
		}
		return resultMap;
	}

	private static Collection arrayToMap(Collection lstObj) {
		ArrayList arrayList = new ArrayList();

		for (Object t : lstObj) {
			if (t instanceof Collection) {
				Collection result = arrayToMap((Collection) t);
				arrayList.add(result);
			} else if (t instanceof Map) {
				Map result = mapToMap((Map) t);
				arrayList.add(result);
			} else {
				if (t instanceof String || t instanceof Boolean || t instanceof Byte || t instanceof Short
						|| t instanceof Integer || t instanceof Long || t instanceof Float || t instanceof Double
						|| t instanceof Enum) {
					if (t != null) {
						arrayList.add(t);
					}
				} else {
					Object result = objectToMap(t);
					arrayList.add(result);
				}
			}
		}
		return arrayList;
	}

}